import * as d3 from 'd3'

export default function({ diagramEl,data }) {
    const element = diagramEl.value;
    let svgTranslate,svgScale;
    const drawDiagram = () => {

        const links = data.links.map(d => Object.create(d));
        const nodes = data.nodes.map(d => Object.create(d));
        const width = 500;
        const height = 600;

        const simulation = d3.forceSimulation(nodes)
            .force("link", d3.forceLink(links).id(d => d.id))
            .force("charge", d3.forceManyBody())
            .force("center", d3.forceCenter(width / 2, height / 2));

        const svg = d3.select('svg')
                      .attr("viewBox", [20, 20, width, height])
                      .attr('class','neo4jd3-graph')
                      .call(d3.zoom().on('zoom',function (){
                          var scale = d3.event.transform.k,
                              translate = [d3.event.transform.x,d3.event.transform.y];
                          if (svgTranslate) {
                              translate[0] += svgTranslate[0];
                              translate[1] += svgTranslate[1];
                          }
                          if (svgScale) {
                              scale *= svgScale;
                          }
                          svg.attr('transform', 'translate(' + translate[0] + ', ' + translate[1] + ') scale(' + scale + ')');
                      }));


        const link = svg.append("g")
            .attr("stroke", "#999")
            .attr("stroke-opacity", 0.6)
            .selectAll("line")
            .data(links)
            .join("line")
            .attr("stroke-width", d => Math.sqrt(d.value));

        const node = svg.append("g")
            .attr("stroke", "#fff")
            .attr("stroke-width", 1.5)
            .selectAll("circle")
            .data(nodes)
            .join("circle")
            .attr("r", 20)
            .attr("fill", color)
            .call(drag(simulation));

        node.append("title")
            .text(d => d.id);

        simulation.on("tick", () => {
            link
                .attr("x1", d => d.source.x)
                .attr("y1", d => d.source.y)
                .attr("x2", d => d.target.x)
                .attr("y2", d => d.target.y);

            node
                .attr("cx", d => d.x)
                .attr("cy", d => d.y);
        });

        return svg.node();
    };

    const drag = simulation => {

        function dragstarted(event) {
            if (!event.active) simulation.alphaTarget(0.3).restart();
            event.subject.fx = event.subject.x;
            event.subject.fy = event.subject.y;
        }

        function dragged(event) {
            event.subject.fx = event.x;
            event.subject.fy = event.y;
        }

        function dragended(event) {
            if (!event.active) simulation.alphaTarget(0);
            event.subject.fx = null;
            event.subject.fy = null;
        }

        return d3.drag()
            .on("start", dragstarted)
            .on("drag", dragged)
            .on("end", dragended);
    }

    const color = () =>{
        const scale = d3.scaleOrdinal(d3.schemeCategory10);
        return d => scale(d.group);
    }

    const redrawDiagram = () => {
        // update props or the whole diagram based on use-case
    };

    const resizeDiagram = () => {
        // resize the diagram to match viewport props
    };

    return {
        drawDiagram,
        redrawDiagram,
        resizeDiagram
    }
}